package com.authority.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.authority.result.PageResult;
import com.google.common.collect.Lists;
import com.suixun.util.DateUtil;

public class CommonUtils {

	private static final Logger log = LoggerFactory.getLogger(CommonUtils.class);

	public static String removeLastWord(String word) {
		if (word.length() > 0) {
			word = word.substring(0, word.length() - 1);
		}
		return word;
	}

	public static Integer int2IntegerIngore(int num, int ignore) {

		if (num == ignore) {
			return null;
		} else {
			return num;
		}
	}

	public static int null2Zero(Integer num) {

		if (num == null) {
			return 0;
		}

		return num;
	}

	// 非int类型的数据会转成0
	public static Integer[] string2IntArr(String word, String split) {

		if (StringUtils.isEmpty(word)) {
			return null;
		}

		String[] strArr = word.split(split);
		Integer[] result = new Integer[strArr.length];

		for (int i = 0; i < strArr.length; i++) {
			result[i] = NumberUtils.toInt(strArr[i]);
		}

		return result;
	}

	public static String getRemoteIpAddr(HttpServletRequest request) {

		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		log.warn("ip: " + ip);
		return ip;
	}

	/**
	 * 通过反射获取fields然后进行赋值; 有继承关系的field无法赋值
	 * 
	 * @param sour
	 * @param dest
	 * @throws Exception
	 */
	public static void doTrans(Object sour, Object dest) throws Exception {

		if (sour == null) {
			dest = null;
			return;
		}

		Class<?> sourClass = sour.getClass();
		Class<?> destClass = dest.getClass();

		for (Field modelField : sourClass.getDeclaredFields()) {

			String fieldName = modelField.getName();
			Object value;

			if (fieldName.equals("serialVersionUID")) {
				continue;
			}

			try {
				PropertyDescriptor pdModel = new PropertyDescriptor(fieldName, sourClass);
				value = pdModel.getReadMethod().invoke(sour);
			} catch (Exception e) {
				if (log.isDebugEnabled()) {
					log.debug(sour.getClass().getName() + " - " + dest.getClass().getName() + " - " + fieldName + " - " + e.getMessage());
				}
				continue;
			}

			if (value == null) {
				continue;
			}

			try {
				PropertyDescriptor pdDto = new PropertyDescriptor(fieldName, destClass);
				pdDto.getWriteMethod().invoke(dest, value);
			} catch (Exception e) {
				if (log.isDebugEnabled()) {
					log.debug(sour.getClass().getName() + " - " + dest.getClass().getName() + " - " + fieldName + " - " + e.getMessage());
				}
				continue;
			}
		}
	}
	/**
	 * 
	 * <p>Title: doTrans</p>
	 * <p> 功能描述:doToVo,将Date型转换成String </p>
	 * @param sour
	 * @param dest
	 * @throws Exception
	 */
	public static void doTrans2(Object sour, Object dest) throws Exception {

		if (sour == null) {
			dest = null;
			return;
		}

		Class<?> sourClass = sour.getClass();
		Class<?> destClass = dest.getClass();

		for (Field modelField : sourClass.getDeclaredFields()) {

			String fieldName = modelField.getName();
			Object value;

			if (fieldName.equals("serialVersionUID")) {
				continue;
			}

			try {
				PropertyDescriptor pdModel = new PropertyDescriptor(fieldName, sourClass);
				value = pdModel.getReadMethod().invoke(sour);
			} catch (Exception e) {
				if (log.isDebugEnabled()) {
					log.debug(sour.getClass().getName() + " - " + dest.getClass().getName() + " - " + fieldName + " - " + e.getMessage());
				}
				continue;
			}

			if (value == null) {
				continue;
			}

			try {
				PropertyDescriptor pdDto = new PropertyDescriptor(fieldName, destClass);
				if ("class java.util.Date".equals(modelField.getGenericType().toString())) {
					pdDto.getWriteMethod().invoke(dest, DateUtil.formatDateToString((Date)value, null));
				}else {
					pdDto.getWriteMethod().invoke(dest, value);
				}
			} catch (Exception e) {
				if (log.isDebugEnabled()) {
					log.debug(sour.getClass().getName() + " - " + dest.getClass().getName() + " - " + fieldName + " - " + e.getMessage());
				}
				continue;
			}
		}
	}

	/**
	 * 通过反射获取所有set为前缀的方法,然后截断set字符串,余下的字符串作为field进行赋值; 优先使用doTrans方法
	 * 
	 * @param sour
	 * @param dest
	 * @throws Exception
	 */
	public static void doTransAll(Object sour, Object dest) throws Exception {

		if (sour == null) {
			dest = null;
			return;
		}

		Class<?> sourClass = sour.getClass();
		Class<?> destClass = dest.getClass();

		for (Method method : sourClass.getMethods()) {

			String methodName = method.getName();

			if (!methodName.startsWith("set")) {
				continue;
			}

			String fieldName = methodName.substring(3);
			Object value;

			if (fieldName.equals("serialVersionUID")) {
				continue;
			}

			try {
				PropertyDescriptor pdModel = new PropertyDescriptor(fieldName, sourClass);
				value = pdModel.getReadMethod().invoke(sour);
			} catch (Exception e) {
				if (log.isDebugEnabled()) {
					log.debug(sour.getClass().getName() + " - " + dest.getClass().getName() + " - " + fieldName + " - " + e.getMessage());
				}
				continue;
			}

			if (value == null) {
				continue;
			}

			try {
				PropertyDescriptor pdDto = new PropertyDescriptor(fieldName, destClass);
				pdDto.getWriteMethod().invoke(dest, value);
			} catch (Exception e) {
				if (log.isDebugEnabled()) {
					log.debug(sour.getClass().getName() + " - " + dest.getClass().getName() + " - " + fieldName + " - " + e.getMessage());
				}
				continue;
			}
		}
	}

	public static final String ATTR_VALUE_CHECK_ERROR = "入参属性值校验异常!";

	public static String strTrim(String str) {
		if (StringUtils.isBlank(str)) {
			return "";
		}
		return str.trim();
	}

	public static Number numTrim(Number num) {
		if (num == null) {
			return 0;
		}
		return num;
	}

	public static <T extends Number> T numTrim1(T num, T key) {
		return (num != null) ? num : key;
	}

	public static Long parseStr2Long(String str, String attrName) {
		Long lon = null;
		if (StringUtils.isBlank(str)) {
			return null;
		}
		try {
			str = str.trim();
			lon = Long.parseLong(str);
		} catch (Exception e) {
			throw new RuntimeException(ATTR_VALUE_CHECK_ERROR + "attrName=" + attrName + ",attrValue=" + str);
		}
		return lon;
	}

	public static Long parseStr2Long(String str) {

		if (StringUtils.isBlank(str)) {
			return null;
		}

		return NumberUtils.toLong(str);
	}

	public static Integer parseStr2Integer(String str, String attrName) {
		Integer in = null;
		if (StringUtils.isBlank(str)) {
			return null;
		}
		try {
			str = str.trim();
			in = Integer.parseInt(str);
		} catch (Exception e) {
			throw new RuntimeException(ATTR_VALUE_CHECK_ERROR + "attrName=" + attrName + ",attrValue=" + str);
		}
		return in;
	}

	public static String parseLong2Str(Long lon) {
		if (lon == null) {
			return "";
		}
		return Long.toString(lon);
	}

	public static String parseInteger2Str(Integer in) {
		if (in == null) {
			return "";
		}
		return Integer.toString(in);
	}
	
	public static String parseDouble2Str(Double dou) {
		if (dou == null) {
			return "";
		}
		return Double.toString(dou);
	}

	public static String parseInt2Str(Integer in) {
		if (in == null) {
			return "";
		}
		return Integer.toString(in);
	}
	
	/**
	 * PageResult<DB>转换成PageResult<VO>
	 */
	public static <D, V> PageResult<V> dbToVo(PageResult<D> dbRes, Class<V> clz, CallBack<D,V> callBack) throws Exception {

		PageResult<V> voRes = new PageResult<V>();
		CommonUtils.doTrans(dbRes, voRes);

		List<V> vos = Lists.newArrayList();
		for (D db : dbRes.getList()) {
			V vo = clz.newInstance();
			CommonUtils.doTrans(db, vo);
			callBack.execute(db,vo);
			vos.add(vo);
		}
		voRes.setList(vos);

		return voRes;
	}
	
	/**
	 * PageResult<DB>转换成PageResult<VO>
	 */
	public static <D, V> PageResult<V> dbToVo(PageResult<D> dbRes, Class<V> clz) throws Exception {

		PageResult<V> voRes = new PageResult<V>();
		CommonUtils.doTrans(dbRes, voRes);

		List<V> vos = Lists.newArrayList();
		for (D db : dbRes.getList()) {
			V vo = clz.newInstance();
			CommonUtils.doTrans(db, vo);
			vos.add(vo);
		}
		voRes.setList(vos);

		return voRes;
	}
	
	
	/**
	 * List<DB>转换成List<VO>
	 */
	public static <D, V> List<V> dbToVo(List<D> dbList, Class<V> clz, CallBack<D,V> callBack) throws Exception {
		
		List<V> voList = Lists.newArrayList();
		for(D db : dbList){
			V vo = clz.newInstance();
			CommonUtils.doTrans(db, vo);
			callBack.execute(db,vo);
			voList.add(vo);
		}
		
		return voList;
	}
	
	/**
	 * List<DB>转换成List<VO>
	 */
	public static <D, V> List<V> dbToVo(List<D> dbList, Class<V> clz) throws Exception {
		
		List<V> voList = Lists.newArrayList();
		for(D db : dbList){
			V vo = clz.newInstance();
			CommonUtils.doTrans(db, vo);
			voList.add(vo);
		}
		
		return voList;
	}
	/**
	 * 
	 * <p>Title: dbToVo2</p>
	 * <p> 功能描述:doToVo，Date型转换为String </p>
	 * @param dbList
	 * @param clz
	 * @return
	 * @throws Exception
	 */
	public static <D, V> List<V> dbToVo2(List<D> dbList, Class<V> clz) throws Exception {
		
		List<V> voList = Lists.newArrayList();
		for(D db : dbList){
			V vo = clz.newInstance();
			CommonUtils.doTrans2(db, vo);
			voList.add(vo);
		}
		
		return voList;
	}
	
	public static <D,V> V dbToVo2(D db,Class<V> clz)  throws Exception {
		
		V vo = clz.newInstance();
		CommonUtils.doTrans2(db, vo);
		
		return vo;
	}
	
	public static <D,V> V dbToVo(D db,Class<V> clz)  throws Exception {
		
		V vo = clz.newInstance();
		CommonUtils.doTrans(db, vo);
		
		return vo;
	}
	
	public static <D,V> V dbToVo(D db,Class<V> clz,CallBack<D,V> callBack)  throws Exception {
		
		V vo = clz.newInstance();
		CommonUtils.doTrans(db, vo);
		callBack.execute(db,vo);
		return vo;
	}
	
	public interface CallBack<D,V> {
		public void execute(D db,V vo);
	}
	
	public  static String setToString(Set<String> set){
		return set.toString().substring(1, set.toString().length()-1);
	}

	public static <T> String listToString(List<T> list){
		
		if(CollectionUtils.isNotEmpty(list)){
			StringBuffer buff = new StringBuffer();
			for(T obj : list){
				buff.append(obj.toString()).append(",");
			}
			return buff.substring(0, buff.length()-1);
		}
		
		return null;
	}

    /**
     * logInfo按参数顺序记录日志
     * 
     * @param logger
     * @param msg
     * @param args
     *            2015年12月18日 下午3:35:32 houchu.zjj
     */
    public static void logInfo(Logger logger, String msg, Object... args) {
	try {
	    StringBuffer log = new StringBuffer();
	    int i = 0;
	    log.append(msg);
	    for (Object arg : args) {
		if (arg == null)
		    arg = "null";
		if (arg instanceof String || arg instanceof Number || arg instanceof Boolean) {
		    log.append(i++).append(":").append(arg.toString()).append(",");
		} else {
		    log.append(i++).append(":").append(JSON.toJSONString(arg)).append(",");
		}

	    }
	    logger.warn(log.toString());
	} catch (Exception e) {
	    logger.error("logging error!", e);
	}

    }
}


